/***********************************************
*   This class is a base API for CFollowersQuery
*
*   with self exception handling
*
*   By GuiQing , (c)2010    Specialisation Level : Generic SQLite
************************************************/

/**********************************************
*
*It's kinda weird that if there's a wxMessageBox in CQuery
*The app crashed. But in other class , wxMessageBox is just peace & quiet
*I think the reason may be the derived hieriacy
*
***********************************************/
#ifndef CQUERY_H_INCLUDED
#define CQUERY_H_INCLUDED

#include "GlobalConfig.h"
#include <vector>
#include <map>
#include "wx/wxsqlite3.h"
#include <wx/event.h>

#define DEFAULT_DB_NAME "data.db"
#define CREATE_TABLE_FOLLOWERS_header "CREATE TABLE "
#define CREATE_TABLE_FOLLOWERS_footer \
            "(\
            id CHAR(12) PRIMARY KEY,\
            screen_name VARCHAR(20),\
            name VARCHAR(20),\
            province VARCHAR(3),\
            city VARCHAR(6),\
            location VARCHAR(20),\
            description VARCHAR(100),\
            url VARCHAR(100),\
            profile_image_url VARCHAR(100),\
            domain VARCHAR(100),\
            gender VARCHAR(6),\
            followers_count INT,\
            friends_count INT,\
            statuses_count INT,\
            favourites_count INT,\
            created_at VARCHAR(50),\
            following VARCHAR(6),\
            verified VARCHAR(6),\
            allow_all_act_msg VARCHAR(6),\
            geo_enabled VARCHAR(6)\
            )"

#define CREATE_TABLE_RECYCLER_footer \
            "(\
            id CHAR(12) PRIMARY KEY,\
            screen_name VARCHAR(20),\
            name VARCHAR(20),\
            province VARCHAR(3),\
            city VARCHAR(6),\
            location VARCHAR(20),\
            description VARCHAR(100),\
            url VARCHAR(100),\
            profile_image_url VARCHAR(100),\
            domain VARCHAR(100),\
            gender VARCHAR(6),\
            followers_count INT,\
            friends_count INT,\
            statuses_count INT,\
            favourites_count INT,\
            created_at VARCHAR(50),\
            following VARCHAR(6),\
            verified VARCHAR(6),\
            allow_all_act_msg VARCHAR(6),\
            geo_enabled VARCHAR(6), \
            last_found_time VARCHAR(50), \
            lost_time VARCHAR(50), \
            profile_image BLOB\
            )"

#define CREATE_TABLE_SYSTEM "CREATE TABLE T_system \
                                                     (\
                                                     key CHAR(12) PRIMARY KEY, \
                                                     value VARCHAR(100)\
                                                      )"

typedef std::vector< std::map<wxString , wxString> > tableType;

#ifdef GUI_DEPENDENT
class wxFrame;
wxDECLARE_EVENT(EVT_UPDATE_SUB_GAUGE, wxThreadEvent);
wxDECLARE_EVENT(EVT_PULSE_SUB_GAUGE, wxThreadEvent);

//Maybe in the SetPayload, wxAny will check for a correct type.
//If there's no explictly specifying, the Assert in wxAny will failed.
#define SUB_GAUGE_UPDATE(text, num, reciever, ID) \
    wxThreadEvent* subGaugeUpdateEvent_##ID = new wxThreadEvent(EVT_UPDATE_SUB_GAUGE);\
    subGaugeUpdateEvent_##ID->SetPayload< std::pair<const wxString, const int> >(std::make_pair(text, num)); \
    wxQueueEvent(reciever, subGaugeUpdateEvent_##ID);

#define SUB_GAUGE_PULSE(reciever)  wxQueueEvent(reciever, new wxThreadEvent(EVT_PULSE_SUB_GAUGE));

#define SUB_GAUGE_LOOP_PULSE(reciever)\
    for(int i=0;i<PULSE_MAX; ++i) \
        if(i%PULSE_UNIT==0) \
            { SUB_GAUGE_PULSE(reciever); };\

#endif

class CQuery
{
    private:
    //When multi-threaded, there can be multiple instance of CQuery
    //But wxSQLite3Database obj can be used only by the thread which create it
    //So wxSQLite3Database can't be shared as a static member
        static wxString dbPath;

        void initNewDB();
        bool extractResult(wxSQLite3ResultSet& queryResult);
        wxString createTableSQL(const wxString& tableName) throw();

    protected:
        wxSQLite3Database db;
        tableType result;
        wxMemoryBuffer* resultBLOB;
        static long num;    //global count number for positioning Progress Bar UI(Gauge)
        #ifdef GUI_DEPENDENT
            wxEvtHandler* gaugeEventReciever;
        #endif
    public:

        CQuery(
        #ifdef GUI_DEPENDENT
            //CQuery sometimes is used for config param querying , in which case pGaugeEventReciever is not required
            wxEvtHandler* pGaugeEventReciever = NULL
        #endif
               );
        virtual ~CQuery();

        bool store(tableType& ramData, const wxString& tableName, long goalNum=-1);
        bool storeBLOB(const wxMemoryBuffer& blobValue, const wxString& tableName, const wxString& colName, const wxString& whereExpr);
        static void setDBpath(const wxString& db_name_IN) throw ();
        tableType& query(const wxString& sql_IN);
        wxMemoryBuffer* queryBLOB(const wxString& sql_IN);
        /**Return by ref is not safe for vital params. It may lead to mem read violation**/
        wxString getSystemParam(const wxString& keyStr);
        bool setSystemParam(const wxString& keyStr , const wxString& valueStr);
        bool deleteSystemParam(const wxString& keyStr);
        int countTable(const wxString& tableName, const wxString& keyField = "id");
};


#endif // CQUERY_H_INCLUDED

